local abacus = AceLibrary("Abacus-2.0")
local dewdrop = AceLibrary("Dewdrop-2.0")
local tablet = AceLibrary("Tablet-2.0")
local AceOO = AceLibrary("AceOO-2.0")

SuperGuild = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceEvent-2.0", "AceDB-2.0")
SuperGuild:RegisterDB("SuperGuild")
SuperGuild:RegisterDefaults("profile", {
    searchPattern = "%[%%a%+%]",
    searchPatternText = "[@]",
    searchNoteType = {
    	guildNote = true,
    	officerNote = false,
    	},    
} )

local SuperGuild = SuperGuild

SuperGuild.roster = {mainless = {},}
SuperGuild.debug = false


-- -----------------------
-- EVENT HANDLERS
-- -----------------------

function SuperGuild:OnEnable()
	self:Print("SuperGuild Enable")
	self:RegisterBucketEvent({"PLAYER_ENTERING_WORLD", "PLAYER_GUILD_UPDATE", "GUILD_ROSTER_UPDATE"},	0, "UpdateRoster")
end

-- -----------------------
-- MAIN FUNCTIONS
-- -----------------------
function SuperGuild:RosterSearch(...)
	self:SetSearchFlagsOff()
	local args = self:ReturnVarArgTable(...)

	for i, v in ipairs(args) do
		v = string.lower(v)
		self:RosterSearch_Name(v)
	end
	
	self:DisplaySearchResults()
end

function SuperGuild:RosterSearch_Name(name)
	for i, entry in ipairs(self.roster) do
		if string.find(entry.main, name, 1, true) then
			entry.found = true
		end
		if not entry.found then
			for i2, alt in ipairs(entry.alts) do
				if string.find(alt, name, 1, true) then
					entry.found = true
				end
			end
		end
	end
end

function SuperGuild:DisplaySearchResults()
	for i, entry in ipairs(self.roster) do
		if entry.found then
			self:Print("Main: %s", entry.main)
			for i2, alt in ipairs(entry.alts) do
				self:Print("   alt: %s", alt)
			end
		end
	end
end

function SuperGuild:UpdateRoster()
	if not IsInGuild() then
		self:Print("cannot update roster, you are not in a guild")
		return
	end

	-- self:Print("updating roster")
	self.roster = {mainless = {},}
	local notes = self:ReturnNotes()
	local tempAltList = {}
	local gNote, oNote
	
	-- find mains
	for k, v in pairs(notes) do
		-- self:Print(k .. ": " .. v.gNote .. " | " .. v.oNote)
		
		if self.db.profile.searchNoteType.guildNote then
			if v.gNote then
				gNote = self:SearchTextForAlt(v.gNote)
			end
		end
		
		if self.db.profile.searchNoteType.officerNote then
			if v.oNote then
				oNote = self:SearchTextForAlt(v.oNote)
			end
		end
		
		if not gNote and not oNote then
			-- self:Print("adding " .. k .. " as main")
			
			table.insert(self.roster, 
			{
				main = k,
				alts = {},
				found = false
			})
		else
			-- self:Print("adding " .. k .. " as alt")
			local main = gNote or oNote
			
			if not tempAltList[main] then
				tempAltList[main] = {k}
			else
				table.insert(tempAltList[main], k)
			end
		end
	end
	
	-- attach alts to mains
	for main, altList in pairs(tempAltList) do
		-- self:Print(main)
		local idx = self:GetIndexByMain(main)
		
		if idx then	
			for i, alt in ipairs(altList) do
				table.insert(self.roster[idx].alts, alt)
			end
		else
			for i, alt in ipairs(altList) do
				-- self:Print("no main(%s) found for alt [%s]", main, alt)
				-- SendChatMessage(string.format("Listed main (%s) not found for character [%s]", main, alt), "OFFICER", nil, nil)
				table.insert(self.roster.mainless, alt)
			end
		end
	end
	
	if self.debug then
		-- debug print verify
		for i, v in ipairs(self.roster) do
			self:Print(v.main)
			for i2, v2 in ipairs(v.alts) do
				self:Print("   " .. v2)
			end
		end
		self:Print("Alts w/o mains")
		for i, v in ipairs(self.roster.mainless) do
			self:Print(v)
		end
	end
end

function SuperGuild:ReturnNotes()
	local notes = {}
	
	-- cache the current showOffline setting, then turn it on
	local showOffline = GetGuildRosterShowOffline()
	SetGuildRosterShowOffline(true)
	
	-- gather all the guild members and notes
	for x = 1, GetNumGuildMembers() do
		local name, _, _, _, _, _, guildNote, officerNote = GetGuildRosterInfo(x)
		name = string.lower(name)
		guildNote = string.lower(guildNote)
		officerNote = string.lower(officerNote)
		notes[name] = {gNote = guildNote, oNote = officerNote}		
	end
		
	-- set the showOffline back to normal
	SetGuildRosterShowOffline(showOffline)
	
	return notes
end

function SuperGuild:SearchTextForAlt(text)
	local _, _, name = string.find(string.lower(text), self.db.profile.searchPattern)
	return name
end

function SuperGuild:UpdateAll()	

end

-- -----------------------
-- GET/SET FUNCTIONS
-- -----------------------

-- ---------------------
-- SearchPattern
function SuperGuild:SetSearchPattern(patternText)
	
	-- validate search pattern
	if not string.find(patternText, "@") then
		self:Print("You have not supplied a name wild-card.  please insert an @ to represent where the player name will be found")
		return
	end
	
	-- if validated, set the search pattern
	local pt = patternText
	local magicChars = {
		-- ^$()%.[]*+-?
		["%^"] = "%%%^",
		["%$"] = "%%%$",
		["%("] = "%%%(",
		["%)"] = "%%%)",
		["%."] = "%%%.",
		["%["] = "%%%[",
		["%]"] = "%%%]",
		["%*"] = "%%%*",
		["%+"] = "%%%+",
		["%-"] = "%%%-",
		["%?"] = "%%%?",
	}
	
	-- format for %
	pt = string.gsub(pt, "%%", "%%%%")
		
	-- format for all other magic chars
	for k, v in pairs (magicChars) do
		pt = string.gsub(pt, k, v)
	end
	
	-- format for key
	pt = string.gsub(pt, "@", "(%%a%+)")
	
	-- if all is good, save off the new patter and patternText
	self.db.profile.searchPattern = pt
	self.db.profile.searchPatternText = patternText
end

function SuperGuild:GetSearchPattern()
	if self.debug then
		self:Print("[Debug] pattern: " .. self.db.profile.searchPattern)
	end
	
	return self.db.profile.searchPatternText
end

-- ---------------------
-- Search Guild Note
function SuperGuild:SetSearchGuildNote(v)
	self.db.profile.searchNoteType.guildNote = v
end

function SuperGuild:GetSearchGuildNote()
	return self.db.profile.searchNoteType.guildNote
end

-- ---------------------
-- Search Officer Note
function SuperGuild:SetSearchOfficerNote(v)
	self.db.profile.searchNoteType.officerNote = v
end

function SuperGuild:GetSearchOfficerNote()
	return self.db.profile.searchNoteType.officerNote
end

-- -----------------------
-- ROSTER FUNCTIONS
-- -----------------------
function SuperGuild:GetIndexByMain(name)
	for i, entry in ipairs(self.roster) do
		if entry.main == name then
			return i
		end
	end
	return nil
end

function SuperGuild:GetIndexByAlt(name)
	for i, entry in ipairs(self.roster) do
		for i2, alt in ipairs(entry.alts) do
			if alt == name then
				return i
			end
		end
	end
	return nil
end
-- -----------------------
-- UTILITY FUNCTIONS
-- -----------------------
function SuperGuild:SetSearchFlagsOff()
	for i, entry in ipairs(self.roster) do
		entry.found = false
	end
end

function SuperGuild:ReturnVarArgTable(...)
	local argTable = {}
	local numVarArgs = select("#", ...)
	for x = 1, numVarArgs do
		local v = select(x, ...)
		table.insert(argTable, v)
	end
	return argTable
end










































-- -----------------------
-- CLASSES
-- -----------------------

--[[
local Player = AceOO.Class()

function Player:ToString()
	return "Player"
end

Player.prototype.main = nil
Player.prototype.foo = {alts = {}}

function Player.prototype:init(name)
	Player.super.prototype.init(self)
	
	if name then
		self.main = name
	else
		SuperGuild:Print("a name was not supplied for the newly created player")
	end
end

function Player.prototype:AddAlt(name)
	if #self.foo.alts < 10 then
		SuperGuild:Print("Adding Alt [%s] to [%s] %d", name, self.main, #self.foo.alts)
		table.insert(self.foo.alts, name)
		
		for i, v in ipairs(self.foo.alts) do
			SuperGuild:Print(v)
		end
	end
end

function Player.prototype:PrintContents()
	SuperGuild:Print(self.main)
--	for i, alt in ipairs(self.alts) do
--		SuperGuild:Print("    " .. alt)
--	end
end



-- <WTF???>
SuperGuild.x = 0
SuperGuild.tests = {}

local test = AceOO.Class()

test.prototype.myList = {}

function test.prototype:add()

	table.insert(self.myList, "foo")
	for i, v in ipairs(self.myList) do
		SuperGuild:Print(v)
	end
end

for x = 1, 5 do
	local foo = test:new()
	foo:add()
	table.insert(SuperGuild.tests, foo)
end

-- </WTF???>
]]